package com.ddpt.permission.export;

import cn.hutool.json.JSONUtil;
import com.lh.center.cache.task.AbstractDelayQueueTask;
import com.lh.center.cache.task.TaskDefinition;
import com.lh.center.common.enums.MarketingApp;
import com.lh.center.common.export.*;
import com.lh.center.common.export.dto.ExportRequestDto;
import com.lh.center.common.export.vo.QueryDataVo;
import com.lh.center.common.task.TaskErrorProcessService;
import com.lh.center.common.upload.DubboFileConfigService;
import com.lh.center.common.upload.FileUploadBean;
import com.lh.center.common.upload.UploadFactory;
import com.lh.center.common.upload.provider.MinioUploadProvider;
import com.lh.center.common.util.LoggerUtil;
import com.lh.center.merchant.api.dubbo.DubboExportService;
import io.seata.common.util.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;

@Slf4j
@Component
public class PerAsyncExportTask extends AbstractDelayQueueTask {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private TaskErrorProcessService taskErrorProcessService;

    @Override
    protected StringRedisTemplate getStringRedisTemplate() {
        return stringRedisTemplate;
    }

    @Override
    protected MarketingApp getApp() {
        return MarketingApp.permission;
    }

    @Override
    protected TaskErrorProcessService getErrorProcessService() {
        return taskErrorProcessService;
    }

    @Override
    protected String getTaskTitle() {
        return "商城相关导出";
    }

    @DubboReference
    private DubboExportService dubboExportService;
    @DubboReference
    private DubboFileConfigService dubboFileConfigService;
    @Resource
    private ExportFactory exportFactory;

    @Override
    protected void execute(TaskDefinition task) {
        ExportRequestBean requestBean = dubboExportService.sel(Long.parseLong(task.getValue()));
        if (requestBean == null || requestBean.getUrl() != null) {
            return;
        }
        ExportRequestDto info = JSONUtil.toBean(requestBean.getDto(), ExportAppEnum.valueOf(requestBean.getApp()).getDtoClass());
        long curTime = System.currentTimeMillis();
        info.setExportStartTime(info.getExportStartTime() == null ? 0 : info.getExportStartTime());
        info.setExportEndTime(info.getExportEndTime() == null ? curTime : info.getExportEndTime());
        ExportQueryService service = exportFactory.getService(info.getExportApp());
        if (service == null) {
            log.info("当前任务【" + task.getValue() + "】发生错误,查询数据时无执行对象");
            //存放在错误队列中
            super.retryError(task, null);
            return;
        }
        List<QueryDataVo> vos = service.query(info);

        String url = null;
        if (CollectionUtils.isNotEmpty(vos)) {
            byte[] bytes = ExportUtil.export(info.getExportName(), vos, new HashSet<>(info.getExportVos()));
            MinioUploadProvider minio = UploadFactory.minio(dubboFileConfigService.getMinioConfig());
            FileUploadBean upload = minio.upload(info.getExportName() + "-" +
                    LocalDateTime.now().format(ExportUtil.formatter) + ".xlsx", null, bytes);
            url = upload != null ? upload.getUrl() : null;
        }

        dubboExportService.process(url, info.getSign(), vos.size());
    }

    @Override
    protected void retryError(TaskDefinition task, Exception e) {
        AsyncExportBean bean = JSONUtil.toBean(task.getValue(), AsyncExportBean.class);
        if (!bean.isConsistency()) {
            //存放在错误队列中
            super.retryError(task, e);
        } else {
            //无限期重试,每次时间翻倍,如果时间超过了1小时，则停止翻倍
            long retryDelayTime = task.getRetryDelayTime();
            if (retryDelayTime < 60 * 60 * 1000) {
                task.setRetryDelayTime(retryDelayTime * 2);
                task.setExecuteTime(retryDelayTime);
                LoggerUtil.error(this.getClass(), e, "当前任务【" + task.getValue() + "】重试后仍然发生错误");
            } else {
                super.retryError(task, e);
            }
            createTask(task);
        }
    }
}
